Adding breadcrumbs to a website seems like an easy task and honestly, it should be. Unfortunately it’s not, unless you want to end up copying the almost-same code in all your pages.
Today I’ll be talking about how to add and manage breadcrumbs in an ASP.NET Core website using SmartBreadcrumbs (1.3.0), a library I created to help me add and manage breadcrumbs easily in my projects.
What are breadcrumbs and why use them
A breadcrumb is a type of secondary navigation that shows a user’s current location in the website as well as the “history” of how he got there.
If your website has hierarchically arranged pages or is starting to have a lot of pages (e.g. e-commerce websites), Breadcrumbs can enhance the users navigation by a lot, reducing even the number of actions/clicks it takes them to do so.
Why isn’t it simple to add them in ASP.NET Core
Adding breadcrumbs to ASP.NET Core isn’t easy because there is no out-of-the-box solution. Which leaves 2 options:
- Manually adding them in every page.
- Using an external library to do so.
Manually adding them in every page
This option shouldn’t and will not be considered because the purpose is to find a better way to handle breadcrumbs, not for us to manually add them every time.
Using an external library
This seems like a better solution, all we have to do is find THE library.
When I was making some websites for a client, I looked for a library that could help me add breadcrumbs to them without a lot of work.
I stumbled upon 2 interesting options:
- MvcSiteMapProviders is a tool that provides flexible menus, breadcrumb trails and SEO features for the ASP.NET MVC framework.
As you might have noticed, it’s only for ASP.NET MVC (v3 and v4) and won’t work for ASP.NET v5 / Core. - DNTBreadCrumb.Core creates custom breadcrumb definitions, based on Twitter bootstrap 3.x features for ASP.NET Core. I was happy when I found this library, until I tested it in my projects. DNBreadCrumb.Core works well with simple websites but not with more complex websites, because it doesn’t handle breadcrumb items coming from different Controllers (at least not out of the box, if I understood correctly), which is a downside for me since I needed that kind of navigation.
So after not finding what I was looking for, I ended up creating my own simple utility library: SmartBreadcrumbs.
About SmartBreadcrumbs
SmartBreadcrumbs is a .NET Core utility library for ASP.NET Core websites to easily add and customize breadcrumbs. It is easy to setup and even easier to use!
How it works
At initialization, SmartBreadcrumbs will create a node hierarchy using all the breadcrumb attributes used on Actions (taken from all the Controllers in your Assembly).
You’ll then be able to use a TagHelper that will check if the current action/controller has a node and will render the breadcrumb element if found.
By default, SmartBreadcrumbs uses Bootstrap 4’s classes to style the breadcrumbs.
Usage
SmartBreadcrumbs is available on Nuget, you can install it directly from the Package Manager or using the console.
Initialization
In your services configuration, add:
csharp services.UseBreadcrumbs(GetType().Assembly);
This will let SmartBreadcrumbs extract all the Breadcrumb attributes and their Controller.Action and create a node hierarchy of them.
If you want to customize the css classes, you can do so using the options parameter:
// These are the classes by default (Bootstrap 4.1)
services.UseBreadcrumbs(GetType().Assembly, options =>
{
TagName = "nav";
TagClasses = "";
OlClasses = "breadcrumb";
LiClasses = "breadcrumb-item";
ActiveLiClasses = "breadcrumb-item active";
SeparatorElement = "<li class=\"separator\">/</li>";
});
The SeperatorElement will be added after each node, use it when you’re using a custom theme/template for example.
Adding nodes
First, you’ll need a Default node, most of the time (if not always) this will be your Home page.
The default node will always be present as the parent, even if not explicitly chosen.
[DefaultBreadcrumb("My home")]
public IActionResult Index()
{
// We set the Home.Index as the default node
// "My home" is the title that the node will use
return View();
}
You can then start adding child nodes:
[Breadcrumb("About us")]
public IActionResult AboutUs()
{
// In this case, the DefaultNode will be the parent of this node.
return View();
}
[Breadcrumb("Contact us", FromAction = "Home.AboutUs")]
public IActionResult ContactUs()
{
// This page is a child of the About us page
return View();
}
You can even use the ViewData in case you want your titles to be taken from it:
[Breadcrumb("ViewData.Title")]
[Breadcrumb("ViewData.Title", CacheTitle = true)]
public IActionResult AboutUs()
{
// In this case, the DefaultNode will be the parent of this node.
return View();
}
Manually setting the current nodes
In some cases, you’ll like to set the current nodes yourself. For example, you want the titles of more than one node to be taken from the database or some other source.
Luckily, SmartBreadcrumbs can trust you on this:
public IActionResult Product(int id)
{
var product = GetProduct(id);
// Manually create the nodes (assuming you used the attribute to create a Default node, otherwise create it manually too).
var categoryNode = new BreadcrumbNode(product.Category.Name, "Controller", "Category", null, new { id = 10 });
// When manually creating nodes, you have the option to use route values in case you need them.
var productNode = new BreadcrumbNode(product.Title, "Controller", "Product", categoryNode);
// All you have to do now is tell SmartBreadcrumbs about this
ViewData["BreadcrumbNode"] = productNode; // Use the last node
return View();
}
This is an e-commerce example where the result would be something like this: Home / Laptops / New ACER laptop
Rendering the breadcrumb
When you’re finished adding all the nodes, the last step is to make use of the TagHelper to render the breadcrumb element:
<breadcrumb></breadcrumb>
@* In your _Layout.cshtml *@
Don’t forget to import SmartBreadcrumbs:
@addTagHelper *, SmartBreadcrumbs
@* In your _ViewImports.cshtml *@
Conclusion
Breadcrumbs can be very helpful in some situations and to be able to add and manage easily can save you a lot of work/time and keeps your code clean.
This is why I created SmartBreadcrumbs, which I now use in every project (when needed of course).